package com.gitee.wsl.ext.number

import kotlin.math.abs
import kotlin.math.pow
import kotlin.math.round

fun Int.toPrettyNumberString(
    millionLabel: String,
    thousandLabel: String,
): String {
    val value = this
    return when {
        value > 1_000_000 ->
            buildString {
                val rounded = round((value / 1_000_000.0) * 10) / 10
                if (rounded % 1 <= 0) {
                    append(rounded.toInt())
                } else {
                    append(rounded)
                }
                append(millionLabel)
            }

        value > 1_000 ->
            buildString {
                val rounded = round((value / 1_000.0) * 10) / 10
                if (rounded % 1 <= 0) {
                    append(rounded.toInt())
                } else {
                    append(rounded)
                }
                append(thousandLabel)
            }

        else ->
            buildString {
                append(value)
            }
    }
}


/**
 * Converts the float receiver as a string with [precision] number of digits after the decimal
 * (rounded) (e.g. 35.72 with precision = 1 will be 35.7, 35.78 with precision = 2 will be 35.80)
 */
fun Float.toPrettyNumberString(precision: Int=2): String {
    return this.toDouble().toPrettyNumberString(precision)
}

/**
 * Converts the float receiver as a string with [precision] number of digits after the decimal
 * (rounded) (e.g. 35.72 with precision = 1 will be 35.7, 35.78 with precision = 2 will be 35.80)
 */
fun Float.toString(precision: Int): String {
    return this.toDouble().toString(precision)
}


/**
 * Converts the number to a string with [precision] number of digits after the decimal (rounded)
 * (e.g. 35.72 with precision = 1 will be 35.7, 35.78 with precision = 2 will be 35.80)
 */
fun Double.toPrettyNumberString(precision: Int = 2): String {
    if(precision==-1) return toString()
    val leftShifted = (round(abs(this) * 10.0.pow(precision))).toInt()
    val s = StringBuilder(leftShifted.toString())

    // left-pad with 0's to ensure enough digits
    for (x in (1..(precision + 1 - s.length))) {
        s.insert(0, "0")
    }

    // insert decimal point
    if (precision != 0) s.insert(s.lastIndex - (precision - 1), ".")

    // (re)insert negative sign
    if (this < 0) {
        s.insert(0, "-")
    }

    return s.toString()
}

/**
 * Converts the number to a string with [precision] number of digits after the decimal (rounded)
 * (e.g. 35.72 with precision = 1 will be 35.7, 35.78 with precision = 2 will be 35.80)
 */
fun Double.toString(precision: Int): String = toPrettyNumberString(precision)